/**
 * Copyright @2024 Transsion Inc
 * Author: jianyun.yang
 * transsion custom feature implementions
*/

#include "TranCustom.h"
#include <sys/wait.h>
#include <string.h>
#include <cutils/properties.h>

#include "PortHandle.h"
#include "MetaPub.h"
#include "LogDefine.h"
#include "libnvram.h"
#include "Context.h"

#ifndef MTK_GENERIC_HAL
#include "Custom_NvRam_LID.h"
#endif

#include <dlfcn.h>
#include <map>
#include <fstream>
#include <string>

/* tranhwInfo service */
#include <stdio.h>
#include <errno.h>
//#include <vendor/mediatek/hardware/tranHwInfo/1.0/ITranHwInfo.h>
//#include <vendor/mediatek/hardware/tranHwInfo/1.0/types.h>

/* for boot type usage */
#define TRAN_BOOTDEV_MMC             (1)
#define TRAN_BOOTDEV_UFS             (2)

/* for read ROM size usage */
#define TRAN_BOOT_TPYE_PATH          "/proc/device-tree/chosen/atag,boot"
#define TRAN_MMC_SIZE_PATH           "/sys/block/mmcblk0/size"
#define TRAN_UFS_SIZE_PATH           "/sys/block/sdc/size"
#define TRAN_RAM_SIZE_PATH           "/proc/meminfo"

//using android::sp;
//using android::hardware::hidl_string;
//using android::hardware::hidl_vec;
//using vendor::mediatek::hardware::tranHwInfo::V1_0::ITranHwInfo;

static void TranMetaReset(FT_CUSTOMER_CNF *ft_cnf, char* peer_buf, int peer_buff_size);
static void TranMetaReboot(FT_CUSTOMER_CNF *ft_cnf, char* peer_buf, int peer_buff_size);
static void TranShellCmdExec(FT_CUSTOMER_CNF *ft_cnf, char* peer_buf, int peer_buff_size);
static void TranReadRomSize(FT_CUSTOMER_CNF *ft_cnf, char* peer_buf, int peer_buff_size);
static void TranReadRamSize(FT_CUSTOMER_CNF *ft_cnf, char* peer_buf, int peer_buff_size);
//USD:modify for P1 charging X6720H353-2 by zhenglong.hong 20240510 start
//static void TranGetBatteryCapacity(FT_CUSTOMER_CNF *ft_cnf, char* peer_buf, int peer_buff_size);
//static void TranGetBatteryVoltage(FT_CUSTOMER_CNF *ft_cnf, char* peer_buf, int peer_buff_size);
//static void TranGetBatteryTemperature(FT_CUSTOMER_CNF *ft_cnf, char* peer_buf, int peer_buff_size);
//USD:modify for P1 charging X6720H353-2 by zhenglong.hong 20240510 end

//static void TranGetEfuseState(FT_CUSTOMER_CNF *ft_cnf, char* peer_buf, int peer_buff_size);

meta_cmd_hdlr custom_cmd_hdlr[]={
    {FT_CUSTOMER_CMD_NONE, (meta_cust_hdlr)nullptr},
    {FT_CUSTOMER_CMD_FRESET, (meta_cust_hdlr)TranMetaReset},
    {FT_CUSTOMER_CMD_REBOOT, (meta_cust_hdlr)TranMetaReboot},
    {FT_CUSTOMER_CMD_SHELL, (meta_cust_hdlr)TranShellCmdExec},
    {FT_CUSTOMER_CMD_READ_ROM_SIZE, (meta_cust_hdlr)TranReadRomSize},
    {FT_CUSTOMER_CMD_READ_RAM_SIZE, (meta_cust_hdlr)TranReadRamSize},
    //USD:modify for P1 charging X6720H353-2 by zhenglong.hong 20240510 start
    //{FT_CUSTOMER_CMD_READ_BATTERY_CAPACITY, (meta_cust_hdlr)TranGetBatteryCapacity},
    //{FT_CUSTOMER_CMD_READ_BATTERY_VOL, (meta_cust_hdlr)TranGetBatteryVoltage},
    //{FT_CUSTOMER_CMD_READ_BATTERY_TEMP, (meta_cust_hdlr)TranGetBatteryTemperature},
    //USD:modify for P1 charging X6720H353-2 by zhenglong.hong 20240510 end

    //{FT_CUSTOMER_CMD_GET_EFUSE_STATE_FLAG,(meta_cust_hdlr)TranGetEfuseState},

    {FT_CUSTOMER_CMD_MAX, (meta_cust_hdlr)nullptr},
};

/* return the index of id in custom_cmd_hdlr[]  */
static int GetCmdIndex(FT_CUSTOMER_REQ *req, meta_cmd_hdlr *cmd_hdlr)
{
    int index = 0;
    char buf[1024];
    META_LOG("[META][FTC] Entry %s\n", __FUNCTION__);
    sprintf(buf, "[META][FTC] Entry %s\n", __FUNCTION__);
    writeBootprof(buf);

    while(cmd_hdlr->cmd_id != FT_CUSTOMER_CMD_MAX) {
        if(req->cmd.m_u1Dummy == cmd_hdlr->cmd_id) {
            META_LOG("[META][FTC] match cmd_id succeed! index = %d\n", index);
            sprintf(buf, "[META][FTC] match cmd_id succeed! index = %d\n", index);
            writeBootprof(buf);
            break;
        }
        index++;
        cmd_hdlr++;
    }
    //if no cmd_id matches
    if(cmd_hdlr->cmd_id == FT_CUSTOMER_CMD_MAX) {
        index = -1;
        META_LOG("[META][FTC] match cmd_id failed! index = %d\n", index);
        sprintf(buf, "[META][FTC] match cmd_id failed! index = %d\n", index);
        writeBootprof(buf);
    }
    return index;
}

/* req->cmd.m_u1Dummy is the cmd id received from PC,
 * there must be an id in custom_cmd_hdlr[] which equal req->cmd.m_u1Dummy,
 * returns the Hdlr which couple with id.
 */
meta_cust_hdlr TranGetCustomCmdHdlr(FT_CUSTOMER_REQ *req)
{
    int index = 0;
    char buf[1024];
    META_LOG("[META][FTC] Entry %s\n", __FUNCTION__);
    sprintf(buf, "[META][FTC] Entry %s\n", __FUNCTION__);
    writeBootprof(buf);
    META_LOG("[META][FTC] cmd_id received from PC is: %d\n", req->cmd.m_u1Dummy);
    sprintf(buf, "[META][FTC] cmd_id received from PC is: %d\n", req->cmd.m_u1Dummy);
    writeBootprof(buf);

    if ((req->cmd.m_u1Dummy <= FT_CUSTOMER_CMD_NONE) || (req->cmd.m_u1Dummy >= FT_CUSTOMER_CMD_MAX)) {
        META_LOG("[META][FTC] cmd_id received from PC is invalid\n");
        writeBootprof((char *)"[META][FTC] cmd_id received from PC is invalid\n");
        return nullptr;
    }
    index = GetCmdIndex(req, custom_cmd_hdlr);
    //if no cmd_id matches
    if (index <= 0) {
        return nullptr;
    }
    return custom_cmd_hdlr[index].cust_fun;
}

/** reset phone **/
/** FT_CUSTOMER_CMD_FRESET = 1 **/
static void TranMetaReset(FT_CUSTOMER_CNF *ft_cnf, char* peer_buf, int peer_buff_size)
{
    char buf[1024];
    META_LOG("[META][FTC] Entry %s\n", __FUNCTION__);
    sprintf(buf, "[META][FTC] Entry %s\n", __FUNCTION__);
    writeBootprof(buf);
    META_LOG("[META][FTC] New way:trigger action in rc file.\n");
    writeBootprof((char *)"[META][FTC] New way:trigger action in rc file.\n");
    if (peer_buff_size != 0) {
        META_LOG("[Meta][FTC] WARNING: peer_buf is not null, *peer_buf = %s\n", peer_buf);
        sprintf(buf, "[Meta][FTC] WARNING: peer_buf is not null, *peer_buf = %s\n", peer_buf);
        writeBootprof(buf);
    }
    property_set("persist.vendor.tran.wipedata","1");
    writeBootprof((char *)"[META][FTC] set persist.vendor.tran.wipedata to 1");
    ft_cnf->result.m_u1Dummy = FT_CUSTOMER_SUCCESS;
    ft_cnf->status = META_SUCCESS;
    WriteDataToPC(ft_cnf, sizeof(*ft_cnf), NULL, 0);
}

/** reboot phone **/
/** FT_CUSTOMER_CMD_REBOOT = 2 **/
static void TranMetaReboot(FT_CUSTOMER_CNF *ft_cnf, char* peer_buf, int peer_buff_size)
{
    char buf[1024];
    META_LOG("[META][FTC] Entry %s\n", __FUNCTION__);
    sprintf(buf, "[META][FTC] Entry %s\n", __FUNCTION__);
    writeBootprof(buf);
    if (peer_buff_size != 0) {
        META_LOG("[Meta][FTC] WARNING: peer_buf is not null, *peer_buf = %s\n", peer_buf);
        sprintf(buf, "[Meta][FTC] WARNING: peer_buf is not null, *peer_buf = %s\n", peer_buf);
        writeBootprof(buf);
    }
    ft_cnf->result.m_u1Dummy = FT_CUSTOMER_SUCCESS;
    ft_cnf->status = META_SUCCESS;
    WriteDataToPC(ft_cnf, sizeof(*ft_cnf), NULL, 0);
    property_set("sys.powerctl","reboot");
    writeBootprof((char *)"[META][FTC] set sys.powerctl to reboot");
}

/** execute shell cmd **/
/** FT_CUSTOMER_CMD_SHELL = 3 **/
static void TranShellCmdExec(FT_CUSTOMER_CNF *ft_cnf, char* peer_buf, int peer_buff_size)
{
    char out_buf[1025] = {0};
    char buf[1024];
    META_LOG("[META][FTC] Entry %s\n", __FUNCTION__);
    sprintf(buf, "[META][FTC] Entry %s\n", __FUNCTION__);
    writeBootprof(buf);

    ft_cnf->result.m_u1Dummy = FT_CUSTOMER_SUCCESS;
    ft_cnf->status = META_SUCCESS;
    if (peer_buff_size <= 0) {
        ft_cnf->result.m_u1Dummy = FT_CUSTOMER_FAILED;
        META_LOG("[Meta][FTC] Shell command is null string");
        writeBootprof((char *)"[Meta][FTC] Shell command is null string");
        return;
    }
    META_LOG("[Meta][FTC] input shell command is:%s", peer_buf);
    sprintf(buf, "[Meta][FTC] input shell command is:%s", peer_buf);
    writeBootprof(buf);
    FILE *file = popen(peer_buf, "r");
    if (NULL == file) {
        META_LOG("[Meta][FTC] popen failed:0x%p, in %s file at %d line \n", file, __FILE__, __LINE__);
        sprintf(buf, "[Meta][FTC] popen failed:0x%p, in %s file at %d line \n", file, __FILE__, __LINE__);
        writeBootprof(buf);
        ft_cnf->result.m_u1Dummy = FT_CUSTOMER_FAILED;
        return;
    }
    int size = fread(out_buf, sizeof(char), sizeof(out_buf) - 1, file);
    if (ferror(file)) {
        META_LOG("[Meta][FTC] fread failed:0x%p, in %s file at %d line \n", file, __FILE__, __LINE__);
        sprintf(buf, "[Meta][FTC] fread failed:0x%p, in %s file at %d line \n", file, __FILE__, __LINE__);
        writeBootprof(buf);
        ft_cnf->result.m_u1Dummy = FT_CUSTOMER_FAILED;
        ft_cnf->status = META_FAILED;
    }
    out_buf[size] = '\0';
    int status = pclose(file);
    if (WIFEXITED(status)) {
        if (WEXITSTATUS(status) != 0) {
            META_LOG("[Meta][FTC] WEXITSTATUS: %i", WEXITSTATUS(status));
            sprintf(buf, "[Meta][FTC] WEXITSTATUS: %i", WEXITSTATUS(status));
            writeBootprof(buf);
            ft_cnf->result.m_u1Dummy = FT_CUSTOMER_FAILED;
            ft_cnf->status = META_FAILED;
        }
    } else if (WIFSIGNALED(status)) {
        META_LOG("[Meta][FTC] WTERMSIG: %i", WTERMSIG(status));
        sprintf(buf, "[Meta][FTC] WTERMSIG: %i", WTERMSIG(status));
        writeBootprof(buf);
        ft_cnf->result.m_u1Dummy = FT_CUSTOMER_FAILED;
        ft_cnf->status = META_FAILED;
    }
    META_LOG("[Meta][FTC] out size:0x%zx, out buf:%s\n", strlen(out_buf), out_buf);
    sprintf(buf, "[Meta][FTC] out size:0x%zx, out buf:%s\n", strlen(out_buf), out_buf);
    writeBootprof(buf);
    WriteDataToPC(ft_cnf, sizeof(*ft_cnf), out_buf, strlen(out_buf));
}

// static void TranGetEfuseState(FT_CUSTOMER_CNF *ft_cnf, char* peer_buf, int peer_buff_size)
// {
//     std::string temp_buf;
//     char out_buf[1] = {0};
//     ft_cnf->result.m_u1Dummy = FT_CUSTOMER_FAILED;
//     ft_cnf->status = META_SUCCESS;
//     META_LOG("[META][FTC] Entry %s\n", __FUNCTION__);

//     if(peer_buff_size != 0) {
//         META_LOG("[Meta][FTC] WARNING: peer_buf is not null, *peer_buf = %s\n", peer_buf);
//     }

//     android::sp<ITranHwInfo> service = ITranHwInfo::getService();
//     if (service != nullptr) {
//         service->tranGetEfuseState([&](hidl_string efuse_state){temp_buf = efuse_state;});
//         if (temp_buf.size() != 0) {
//             META_LOG("[Meta][FTC] efuse name = %s\n",temp_buf.c_str());
//             ft_cnf->result.m_u1Dummy = FT_CUSTOMER_SUCCESS;
//             if (memcmp("hw",temp_buf.c_str(),2)) {
//                 out_buf[0] = 0;
//             } else {
//                 out_buf[0] = 1;
//             }
//         } else {
//             META_LOG("[Meta][FTC] Failed to get efuse state!\n");
//         }
//     } else {
//         META_LOG("[Meta][FTC] Failed to get TranHwInfo service!\n");
//     }
//     WriteDataToPC(ft_cnf, sizeof(*ft_cnf),out_buf, sizeof(out_buf));
// }

//USD:modify for P1 charging X6720H353-2 by zhenglong.hong 20240510 start
/* shell:cat /sys/class/power_supply/battery/capacity
 * for battery capacity read
 */
/** FT_CUSTOMER_CMD_READ_BATTERY_CAPACITY = 216 **/
// static void TranGetBatteryCapacity(FT_CUSTOMER_CNF *ft_cnf, char* peer_buf, int peer_buff_size)
// {
//     int batteryCapacity = 0;
//     char out_buf[32] = {0};

//     META_LOG("[META][FTC] Entry %s\n", __FUNCTION__);
//     if (peer_buff_size != 0) {
//         META_LOG("[Meta][FTC] WARNING: peer_buf is not null, *peer_buf = %s\n", peer_buf);
//     }

//     android::sp<ITranHwInfo> service = ITranHwInfo::getService();
//     if (service != nullptr) {
//         batteryCapacity = service->tranGetBatteryCapcity();
//         if (batteryCapacity != -1) {
//             META_LOG("[Meta][FTC] battery Capacity = %d\n", batteryCapacity);
//             ft_cnf->result.m_u1Dummy = FT_CUSTOMER_SUCCESS;
//             ft_cnf->status = META_SUCCESS;
//         } else {
//             ft_cnf->result.m_u1Dummy = FT_CUSTOMER_FAILED;
//             META_LOG("[Meta][FTC] Failed to get battery Capacity!\n");
//         }
//     } else {
//         ft_cnf->result.m_u1Dummy = FT_CUSTOMER_FAILED;
//         META_LOG("[Meta][FTC] Failed to get TranHwInfo service!\n");
//     }
//     sprintf(out_buf, "%d", batteryCapacity);
//     WriteDataToPC(ft_cnf, sizeof(*ft_cnf), out_buf, sizeof(out_buf));
// }

/* shell:cat /sys/class/power_supply/battery/batt_vol
 * for battery Voltage read
 */
/** FT_CUSTOMER_CMD_READ_BATTERY_VOL = 217 **/
// static void TranGetBatteryVoltage(FT_CUSTOMER_CNF *ft_cnf, char* peer_buf, int peer_buff_size)
// {
//     int batteryVoltage = 0;
//     char out_buf[32] = {0};

//     META_LOG("[META][FTC] Entry %s\n", __FUNCTION__);
//     if (peer_buff_size != 0) {
//         META_LOG("[Meta][FTC] WARNING: peer_buf is not null, *peer_buf = %s\n", peer_buf);
//     }

//     android::sp<ITranHwInfo> service = ITranHwInfo::getService();
//     if (service != nullptr) {
//         batteryVoltage = service->tranGetBatteryVoltageNow();
//         if (batteryVoltage != -1) {
//             META_LOG("[Meta][FTC] emmc id: %d\n", batteryVoltage);
//             ft_cnf->result.m_u1Dummy = FT_CUSTOMER_SUCCESS;
//             ft_cnf->status = META_SUCCESS;
//         } else {
//             ft_cnf->result.m_u1Dummy = FT_CUSTOMER_FAILED;
//             META_LOG("[Meta][FTC] Failed to get current memory(EmmcID)!\n");
//         }
//     } else {
//         ft_cnf->result.m_u1Dummy = FT_CUSTOMER_FAILED;
//         META_LOG("[Meta][FTC] Failed to get TranHwInfo service!\n");
//     }
//     sprintf(out_buf, "%d", batteryVoltage);
//     WriteDataToPC(ft_cnf, sizeof(*ft_cnf), out_buf, sizeof(out_buf));
// }

/* shell:cat /sys/class/power_supply/battery/batt_temp
 * for battery Temperature read
 */
/** FT_CUSTOMER_CMD_READ_BATTERY_TEMP = 218 **/
// static void TranGetBatteryTemperature(FT_CUSTOMER_CNF *ft_cnf, char* peer_buf, int peer_buff_size)
// {
//     int batteryTemp = 0;
//     char out_buf[32] = {0};
//     META_LOG("[META][FTC] Entry %s\n", __FUNCTION__);

//     if (peer_buff_size != 0) {
//         META_LOG("[Meta][FTC] WARNING: peer_buf is not null, *peer_buf = %s\n", peer_buf);
//     }
//     android::sp<ITranHwInfo> service = ITranHwInfo::getService();
//     if (service != nullptr) {
//         batteryTemp = service->tranGetBatteryTemp();
//         if (batteryTemp != -1) {
//             META_LOG("[Meta][FTC] battery Temp = %d\n",batteryTemp);
//             ft_cnf->result.m_u1Dummy = FT_CUSTOMER_SUCCESS;
//             ft_cnf->status = META_SUCCESS;
//         } else {
//             ft_cnf->result.m_u1Dummy = FT_CUSTOMER_FAILED;
//             META_LOG("[Meta][FTC] Failed to get battery Temp!\n");
//         }
//     } else {
//         ft_cnf->result.m_u1Dummy = FT_CUSTOMER_FAILED;
//         META_LOG("[Meta][FTC] Failed to get TranHwInfo service!\n");
//     }
//     sprintf(out_buf, "%d", batteryTemp);
//     WriteDataToPC(ft_cnf, sizeof(*ft_cnf), out_buf, sizeof(out_buf));
// }
//USD:modify for P1 charging X6720H353-2 by zhenglong.hong 20240510 end

/*boot type: ufs or emmc*/
static int TranGetBootType(char const *path)
{
    int boot_type = 0;
    int buff[4] = {0};
    int fd, rsize;
    char buf[1024];

    fd = open(path, O_RDONLY);
    if (fd >= 0) {
        rsize = read(fd, buff, sizeof(buff));
        if (rsize > 0) {
            META_LOG("[Meta][FTC] read boot type len=%d, buff[0], [1], [2], [3] = %d,%d,%d,%d\n", rsize, buff[0], buff[1], buff[2], buff[3]);
            sprintf(buf, "[Meta][FTC] read boot type len=%d, buff[0], [1], [2], [3] = %d,%d,%d,%d\n", rsize, buff[0], buff[1], buff[2], buff[3]);
            writeBootprof(buf);
            boot_type = buff[3];
        } else {
            META_LOG("[Meta][FTC] read boot type failed! error = %s\n",strerror(errno));
            sprintf(buf, "[Meta][FTC] read boot type failed! error = %s\n",strerror(errno));
            writeBootprof(buf);
        }
        close(fd);
    } else {
        META_LOG("[Meta][FTC] open boot type file %s failed! error = %s\n", path, strerror(errno));
        sprintf(buf, "[Meta][FTC] open boot type file %s failed! error = %s\n", path, strerror(errno));
        writeBootprof(buf);
    }

    if ((boot_type > 2) || (boot_type <= 0))
        boot_type = TRAN_BOOTDEV_MMC;

    META_LOG("[Meta][FTC] boot type: %s\n", (boot_type == TRAN_BOOTDEV_MMC) ? "eMMC":"UFS");
    sprintf(buf, "[Meta][FTC] boot type: %s\n", (boot_type == TRAN_BOOTDEV_MMC) ? "eMMC":"UFS");
    writeBootprof(buf);
    return boot_type;
}

/* shell:
 * emmc: cat /sys/block/mmcblk0/size
 * ufs: cat /sys/block/sdc/size
 * for ROM capacity read
 * it should made a distinction between UFS and Emmc
 */
static bool tran_read_rom_size(char const *path, char *out_buf, size_t buf_len)
{
    int fd, rsize;
    char buf[1024];
    META_LOG("[Meta][FT] enter tran_read_mem_size\n");
    writeBootprof((char *)"[Meta][FT] enter tran_read_mem_size\n");

    if ((fd = open(path, O_RDONLY)) < 0) {
        META_LOG("[Meta][FT] open %s failed! error = %s\n", path, strerror(errno));
        sprintf(buf, "[Meta][FT] open %s failed! error = %s\n", path, strerror(errno));
        writeBootprof(buf);
        return false;
    }
    rsize = read(fd, out_buf, buf_len);
    if (rsize <= 0) {
        META_LOG("[Meta][FT] read %s failed! error = %s\n", path, strerror(errno));
        sprintf(buf, "[Meta][FT] read %s failed! error = %s\n", path, strerror(errno));
        writeBootprof(buf);
        close(fd);
        return false;
    } else {
        close(fd);
        return true;
    }
}

/** FT_CUSTOMER_CMD_READ_ROM_SIZE = 211 **/
static void TranReadRomSize(FT_CUSTOMER_CNF *ft_cnf, char* peer_buf, int peer_buff_size)
{
    char out_buf[32] = {0};
    int tran_boot_type = 0;
    bool ret = false;
    char buf[1024];

    META_LOG("[META][FTC] Entry %s\n", __FUNCTION__);
    sprintf(buf, "[META][FTC] Entry %s\n", __FUNCTION__);
    writeBootprof(buf);
    if (peer_buff_size != 0) {
        META_LOG("[Meta][FTC] WARNING: peer_buf is not null, *peer_buf = %s\n", peer_buf);
        sprintf(buf, "[Meta][FTC] WARNING: peer_buf is not null, *peer_buf = %s\n", peer_buf);
        writeBootprof(buf);
    }
    tran_boot_type = TranGetBootType(TRAN_BOOT_TPYE_PATH);

    if (tran_boot_type == TRAN_BOOTDEV_UFS) {
        ret = tran_read_rom_size(TRAN_UFS_SIZE_PATH, out_buf, sizeof(out_buf));
    } else {
        ret = tran_read_rom_size(TRAN_MMC_SIZE_PATH, out_buf, sizeof(out_buf));
    }
    if (ret) {
        META_LOG("[Meta][FTC] read ROM size succeed!, out_buf = %s\n", out_buf);
        sprintf(buf, "[Meta][FTC] read ROM size succeed!, out_buf = %s\n", out_buf);
        writeBootprof(buf);
        ft_cnf->status = META_SUCCESS;
        ft_cnf->result.m_u1Dummy = FT_CUSTOMER_SUCCESS;
    } else {
        META_LOG("[Meta][FTC] read ROM size failed!\n");
        writeBootprof((char *)"[Meta][FTC] read ROM size failed!\n");
        ft_cnf->result.m_u1Dummy = FT_CUSTOMER_FAILED;
    }
    WriteDataToPC(ft_cnf, sizeof(*ft_cnf), out_buf, sizeof(out_buf));
}

/* ram capacity */
static bool TranReadRamSizePath(char const *path, char *out_buf, size_t buf_len)
{
    char *line = NULL;
    size_t linelen = 0;
    FILE *fp;
    char buf[1024];
    META_LOG("[Meta][FTC] enter tran_read_mam_size\n");
    writeBootprof((char *)"[Meta][FTC] enter tran_read_mam_size\n");
    if (access(path, F_OK|R_OK) != 0) {
        META_LOG("[Meta][FTC] access %s failed! error = %s\n", path, strerror(errno));
        sprintf(buf, "[Meta][FTC] access %s failed! error = %s\n", path, strerror(errno));
        writeBootprof(buf);
        return false;
    }
    fp = fopen(path, "r");
    if (!fp) {
        META_LOG("[Meta][FTC] open %s failed! error = %s\n", path, strerror(errno));
        sprintf(buf, "[Meta][FTC] open %s failed! error = %s\n", path, strerror(errno));
        writeBootprof(buf);
        return false;
    }
    while (getline(&line, &linelen, fp) > 0) {
        if (sscanf(line, "MemTotal: %s kB", out_buf) == 1) {
            buf_len = strlen(out_buf);
            fclose(fp);
            return true;
        }
    }
    fclose(fp);
    META_LOG("[Meta][FTC] no item matches 'MemTotal'!\n");
    writeBootprof((char *)"[Meta][FTC] no item matches 'MemTotal'!\n");
    return false;
}

/* shell:cat /proc/meminfo | grep MemTotal
 * for RAM capacity read
 */
/** FT_CUSTOMER_CMD_READ_RAM_SIZE = 212 **/
static void TranReadRamSize(FT_CUSTOMER_CNF *ft_cnf, char* peer_buf, int peer_buff_size)
{
    char out_buf[32] = {0};
    bool ret = false;
    char buf[1024];
    META_LOG("[META][FTC] Entry %s\n", __FUNCTION__);
    sprintf(buf, "[META][FTC] Entry %s\n", __FUNCTION__);
    writeBootprof(buf);
    if (peer_buff_size != 0) {
        META_LOG("[Meta][FTC] WARNING: peer_buf is not null, *peer_buf = %s\n", peer_buf);
        sprintf(buf, "[Meta][FTC] WARNING: peer_buf is not null, *peer_buf = %s\n", peer_buf);
        writeBootprof(buf);
    }
    ret = TranReadRamSizePath(TRAN_RAM_SIZE_PATH, out_buf, sizeof(out_buf));
    if (ret) {
        META_LOG("[Meta][FTC] read RAM size succeed!, out_buf = %s\n", out_buf);
        sprintf(buf, "[Meta][FTC] read RAM size succeed!, out_buf = %s\n", out_buf);
        writeBootprof(buf);
        ft_cnf->status = META_SUCCESS;
        ft_cnf->result.m_u1Dummy = FT_CUSTOMER_SUCCESS;
    } else {
        META_LOG("[Meta][FTC] read RAM size failed!\n");
        writeBootprof((char *)"[Meta][FTC] read RAM size failed!\n");
        ft_cnf->result.m_u1Dummy = FT_CUSTOMER_FAILED;
    }
    WriteDataToPC(ft_cnf, sizeof(*ft_cnf), out_buf, sizeof(out_buf));
}